//
// AttributeDialog.java
//
package com.photoexpert;

import com.drew.metadata.Directory;
import com.drew.metadata.Tag;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.SampleModel;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import javax.swing.table.DefaultTableModel;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

class AttributeDialog extends javax.swing.JDialog {

    static AttributeDialog Instance() {
        if(_instance == null)
            _instance = new AttributeDialog();
        return _instance;
    }

    void clearAttributes() {
        _attributes.clear();
    }

    void addAttribute(String name, String value) {
        _attributes.put(name, value);
    }

    void addNode(String prefix, Node node) {
        String name = prefix + "." + node.getNodeName();
        String value = node.getNodeValue();
        if(value != null)
            _attributes.put(name, value);
        // add attributes
        if(node.hasAttributes()) {
            NamedNodeMap map = node.getAttributes();
            for(int i = 0; i < map.getLength(); ++i)
                addNode(name, map.item(i));
        }
        // add child nodes
        if(node.hasChildNodes()) {
            NodeList list = node.getChildNodes();
            for(int i = 0; i < list.getLength(); ++i)
                addNode(name, list.item(i));
        }
    }

    void addDirectory(Directory directory) {
        Collection<Tag> tags = directory.getTags();
        for(Tag tag : tags)
            addTag(tag);
    }

    void addTag(Tag tag) {
        _attributes.put(tag.getTagName(), tag.getDescription());
    }

    void display() {
        BufferedImage img = Implementor.Instance().getImage();
        _tableModel.setRowCount(8 + _attributes.size());
        _tableModel.setValueAt("ImageType", 0, 0);
        _tableModel.setValueAt(_typeMap.get(img.getType()), 0, 1);
        int width = img.getWidth();
        _tableModel.setValueAt("Width", 1, 0);
        _tableModel.setValueAt(new Integer(width).toString(), 1, 1);
        int height = img.getHeight();
        _tableModel.setValueAt("Height", 2, 0);
        _tableModel.setValueAt(new Integer(height).toString(), 2, 1);
        ColorModel cm = img.getColorModel();
        String s = cm.getClass().getName();
        _tableModel.setValueAt("ColorModel", 3, 0);
        _tableModel.setValueAt(s.substring(s.lastIndexOf(".") + 1), 3, 1);
        ColorSpace cs = cm.getColorSpace();
        s = Integer.toString(cs.getType());
        if(cs.isCS_sRGB())
            s += "(sRGB)";
        _tableModel.setValueAt("ColorSpace", 4, 0);
        _tableModel.setValueAt(s, 4, 1);
        _tableModel.setValueAt("TransferType", 5, 0);
        _tableModel.setValueAt(_transferTypeMap.get(cm.getTransferType()), 5, 1);
        SampleModel sm = img.getSampleModel();
        s = sm.getClass().getName();
        _tableModel.setValueAt("SampleModel", 6, 0);
        _tableModel.setValueAt(s.substring(s.lastIndexOf(".") + 1), 6, 1);
        int iTransparency = img.getTransparency();
        String sTransparency = iTransparency == Transparency.TRANSLUCENT ? "Translucent" :
                iTransparency == Transparency.OPAQUE ? "Opaque" : "Bitmask";
        _tableModel.setValueAt("Transparency", 7, 0);
        _tableModel.setValueAt(sTransparency, 7, 1);
        int row = 8;
        for(String name: _attributes.keySet() ) {
            _tableModel.setValueAt(name, row, 0);
            _tableModel.setValueAt(_attributes.get(name), row, 1);
            row++;
        }
        setVisible(true);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        _table = new javax.swing.JTable();
        _cancel = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Image Attributes");
        setModal(true);

        _table.setModel(_tableModel);
        jScrollPane1.setViewportView(_table);
        _table.getColumnModel().getColumn(0).setPreferredWidth(20);

        _cancel.setText("Cancel");
        _cancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                _cancelActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 524, Short.MAX_VALUE)
                    .addComponent(_cancel))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 243, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(_cancel)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void _cancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event__cancelActionPerformed
    setVisible(false);
}//GEN-LAST:event__cancelActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton _cancel;
    private javax.swing.JTable _table;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables

    private static AttributeDialog          _instance = null;
    private HashMap<Integer, String>        _typeMap = new HashMap<Integer, String>();
    private HashMap<Integer, String>        _transferTypeMap = new HashMap<Integer, String>();
    private LinkedHashMap<String, String>   _attributes = new LinkedHashMap<String, String>();
    private DefaultTableModel               _tableModel;

    private AttributeDialog() {
        super(App.Instance(), true);
        _tableModel = new DefaultTableModel(new Object [][] { }, new String [] { "Name", "Value" } ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class
            };
            @Override
            public Class getColumnClass(int columnIndex) {
                return types[columnIndex];
            }
            @Override
            public boolean isCellEditable(int rowIndex, int columnIndex) { return false; }
        };
        initComponents();
        setLocation(200, 200);
        _typeMap.put(BufferedImage.TYPE_3BYTE_BGR, "8-bit BGR color in 3 bytes");
        _typeMap.put(BufferedImage.TYPE_4BYTE_ABGR , "8-bit BGR color in 3 bytes and 1 byte alpha");
        _typeMap.put(BufferedImage.TYPE_4BYTE_ABGR_PRE , "8-bit BGR color in 3 bytes and 1 byte of alpha(pre)");
        _typeMap.put(BufferedImage.TYPE_BYTE_BINARY , "opaque byte-packed 1, 2, or 4 bit image");
        _typeMap.put(BufferedImage.TYPE_BYTE_GRAY , "unsigned byte grayscale image, non-indexed");
        _typeMap.put(BufferedImage.TYPE_BYTE_INDEXED , "indexed byte image");
        _typeMap.put(BufferedImage.TYPE_INT_ARGB , "8-bit RGBA color packed into integer pixels");
        _typeMap.put(BufferedImage.TYPE_INT_ARGB_PRE , "8-bit RGBA color packed into integer pixels(pre)");
        _typeMap.put(BufferedImage.TYPE_INT_BGR , "8-bit BGR color packed into integer pixels");
        _typeMap.put(BufferedImage.TYPE_INT_RGB , "8-bit RGB color packed into integer pixels");
        _typeMap.put(BufferedImage.TYPE_USHORT_555_RGB , "5-5-5 RGB color with no alpha");
        _typeMap.put(BufferedImage.TYPE_USHORT_565_RGB , "5-6-5 RGB color with no alpha");
        _typeMap.put(BufferedImage.TYPE_USHORT_GRAY ,  "unsigned short grayscale image, non-indexed");
        _typeMap.put(BufferedImage.TYPE_CUSTOM, "not recognized");
        _transferTypeMap.put(DataBuffer.TYPE_BYTE, "byte");
        _transferTypeMap.put(DataBuffer.TYPE_DOUBLE, "double");
        _transferTypeMap.put(DataBuffer.TYPE_FLOAT, "float");
        _transferTypeMap.put(DataBuffer.TYPE_INT, "integer");
        _transferTypeMap.put(DataBuffer.TYPE_SHORT, "short");
        _transferTypeMap.put(DataBuffer.TYPE_UNDEFINED, "undefined");
        _transferTypeMap.put(DataBuffer.TYPE_USHORT, "unsigned short");
    }
}
